/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "rs_render_process.h"

#include <unistd.h>
#include <malloc.h>
#include <parameters.h>
#include <iservice_registry.h>
#include <system_ability_definition.h>
#include <if_system_ability_manager.h>
#include <platform/common/rs_log.h>
#include "platform/common/rs_system_properties.h"

#include "pipelien/render_process/rs_render_process_connection.h"
#include "pipeline/main_thread/rs_main_thread.h"
#include "rs_trace.h"
#include "graphic_feature_param_manager.h"
#include "pipeline/rs_uni_render_judgement.h"

#undef LOG_TAG
#define LOG_TAG "RSRenderProcess"

namespace OHOS {
namespace Rosen{
namespace {
sptr<RSIRenderService> ConnectToServer()
{
    int tryCnt = 0;
    sptr<RSIRenderService> renderService = nullptr;
    do {
        // sleep move time (1000us * tryCnt) when tryCnt++
        usleep(1000 * tryCnt);
        ++tryCnt;
        // try most 5 times to get render service.
        if (tryCnt == 5) {
            RS_LOGE("%{public}s: tried 5 times.", __func__);
            break;
        }

        auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
        if (samgr == nullptr) {
            RS_LOGE("%{public}s: samgr is null.", __func__);
            continue;
        }
        auto remoteObject = samgr->GetSystemAbility(RENDER_SERVICE);
        if (remoteObject == nullptr) {
            RS_LOGE("%{public}s: remoteObject is null.", __func__);
            continue;
        }
        renderService = iface_cast<RSIRenderService>(remoteObject);
        if (renderService != nullptr) {
            RS_LOGE("%{public}s: renderService is null.", __func__);
            break;
        }
    } while (true);

    if (renderService == nullptr) {
        RS_LOGE("%{public}s: Failed to get renderService proxy.", __func__);
        return nullptr;
    }
    return renderService;
}
}

bool RSRenderProcess::Init()
{
    // 注册子进程到主进程
    RS_LOGD("%{public}s: Init.", __func__);
    if (!RegisterRenderProcessConnection()) {
        RS_LOGE("%{public}s: renderProcess registration failed.", __func__);
        return false;
    }

    // 多进程独有初始化

    // 核心组件初始化
    // 子进程runner_, handler_
    runner_ = AppExecFwk::EventRunner::Create(false);
    handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);

    // receiver_
    sptr<VSyncIConnectionToken> token = new IRemoteStub<VSyncIConnectionToken>();
    sptr<IVSyncConnection> conn = renderComposeConnection_->CreateVSyncConnection(token);
    receiver_ = std::mak_shared<VSyncReceiver>(conn, token->AsObject(), handler_, "rs");

    // 渲染管线拉起
    // mainThread_ = RSMainThread::Instance();
    // mainThread_->Init(runner_, handler_, receiver_);

    return true;
}

void RSRenderProcess::Run()
{
    // 消息队列死循环
    if (runner_) {
        RS_LOGI("fqy %{public}s: SubProcess Run", __func__);
        runner_->Run();
    }
}

sptr<RSIRenderService> RSRenderProcess::GetRenderServer()
{
    // 到sa获取主进程
    if (renderServer_ == nullptr) {
        renderServer_ = ConnectToServer();
    }
    return renderServer_;
}

bool RSRenderProcess:RegisterRenderProcessConnection()
{
    // 注册子进程到主进程
    auto renderServer = GetRenderServer();
    if (UNLIKELY(renderServer == nullptr)) {
        RS_LOGE("%{public}s: renderServer is null.", __func__);
        return false;
    }

    // TODO: 需要一个接口获取当前子进程的screenId
    // auto screenId = GetScreenId();
    auto screenId = 0;
    auto renderProcessConnection = sptr<RSRenderProcessConnection>::MakeSptr(*this);
    auto renderComposeConnection = renderServer->RegisterRenderProcessConnection(renderProcessConnection, screenId);
    if (renderComposeConnection_ == nullptr) {
        RS_LOGE("%{public}s: renderComposeConnection is null.", __func__);
        return false;
    }

    // TODO: 添加死亡监听

    return true;
}

} // namespace Rosen
} // namespace OHOS